package com.cloud.mqtt;

import com.cloud.configure.MqttConfiguration;
import com.cloud.message.QTMessageBuilder;
import org.eclipse.paho.client.mqttv3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class MqttProducer {

    private static Logger logger = LoggerFactory.getLogger(MqttProducer.class);

    @Autowired
    private MqttConfiguration mqttConnect;

    /**
     * MQTT发送指令:主要是组装消息体
     * 消息等级
     * level 0消息最多传递一次,不再关心它有没有发送到对方，也不设置任何重发机制
     * level 1包含了简单的重发机制,发送消息之后等待接收者的回复,如果没收到回复则重新发送消息
     * 这种模式能保证消息至少能到达一次,但无法保证消息重复
     * level 2有了重发和重复消息发现机制,保证消息到达对方并且严格只到达一次
     *
     * @param topic   主题
     * @param message 消息内容
     * @param qos     消息级别
     * @return
     */
    public boolean publish(String topic, Object message, int qos) {
        try {
            MqttClient mqttClient = mqttConnect.getMqttProducer();
            MqttTopic mqttTopic = mqttClient.getTopic(topic);
            // 把消息发送给对应的主题
            MqttMessage mqttMessage = QTMessageBuilder.message(topic, qos, message).build();
            MqttDeliveryToken token = mqttTopic.publish(mqttMessage);
            token.waitForCompletion();
            // 检查消息发送是否成功
            if (token.isComplete()) {
                return true;
            } else {
                return false;
            }
        } catch (MqttException e) {
            logger.error("Mqtt发送消息失败", e);
        }
        return false;
    }


    /**
     * 订阅端取消订阅消息
     *
     * @param topic    要订阅的主题
     * @param callback 订阅者则添加回调类,创建类要实现implements MqttCallback
     */
    public boolean cancelSubscribe(String topic, MqttCallback callback) {
        try {
            MqttClient mqttClient = mqttConnect.getMqttProducer();
            // 取消订阅需要接收结果设置回调
            mqttClient.setCallback(callback);
            // 调用unsubscribe()取消订阅关系
            mqttClient.unsubscribe(topic);
            return true;
        } catch (MqttException e) {
            logger.error("Mqtt订阅者,取消订阅失败", e);
        }
        return false;
    }

}
